package com.sskj.ws.server;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sskj.common.util.StrUtil;
import com.sskj.ws.dto.BasicMessage;
import com.sskj.ws.factory.MessageServiceFactory;
import com.sskj.ws.service.IMessageService;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;

@Component
@ServerEndpoint("/ws")
@Slf4j
public class WebSocketServer {

    @Getter
    private final static CopyOnWriteArraySet<WebSocketServer> webSocketServers = new CopyOnWriteArraySet<>();

    @Getter
    private Session session;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private MessageServiceFactory messageServiceFactory;

    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        webSocketServers.add(this);
        log.info("有新的客户端连接");
    }

    @OnClose
    public void onClose() {
        webSocketServers.remove(this);
        log.info("客户端断开连接");
    }

    @OnMessage
    public void onMessage(String message, Session session) {
//        log.info("来自客户端的消息: {}", message);
        if (StrUtil.isNotBlank(message)) {
            try {
                JsonNode jsonNode = objectMapper.readTree(message);
                String type = jsonNode.get("type").asText();

                IMessageService<?> messageService = messageServiceFactory.getMessageService(type);
                if (messageService == null) {
                    Map<String, String> resp = new HashMap<>();
                    resp.put("type", "error");
                    resp.put("message", "unsupported message type");

                    String jsonData = objectMapper.writeValueAsString(resp);
                    try {
                        session.getBasicRemote().sendText(jsonData);
                    } catch (IOException ignored) {}
                } else {
                    Class<?> messageClass = messageService.getMessageClass();
                    BasicMessage basicMessage = (BasicMessage) objectMapper.readValue(message, messageClass);
                    handleMessage(messageService, basicMessage, session);
                }
            } catch (JsonProcessingException e) {
                log.error("[客户端消息监听]-序列化信息异常。异常信息:{}|内容:{}", e.getMessage(), message);
                try {
                    Map<String, String> resp = new HashMap<>();
                    resp.put("type", "error");
                    resp.put("message", "invalid message format");

                    String jsonData = objectMapper.writeValueAsString(resp);
                    session.getBasicRemote().sendText(jsonData);
                } catch (IOException e1) {
                    log.error("[客户端消息监听]-响应客户端异常。异常信息:{}", e1.getMessage());
                }
            }
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.error("WebSocket 发生错误，Session ID: {}, 错误: {}", session.getId(), error.getMessage());
        webSocketServers.remove(this);
    }


    /**
     * 处理消息
     * @param messageService 处理消息服务类
     * @param message 消息体
     * @param session 会话
     */
    @SuppressWarnings("unchecked")
    private void handleMessage(IMessageService<?> messageService, BasicMessage message, Session session) {
        ((IMessageService<BasicMessage>) messageService).handle(message, session);
    }
}
